import { getPeriodEndDate } from "@/utils";
import { useUpdateEffect } from "ahooks";
import { useState, useRef } from "react";

interface ConstructionPlan {
  constructionProjectName: string;
  constructionPlanId: number;
  constructionPlanTemplateId: number;
  prePlanId: number;
  planStartDate: string;
  planFinishDate: string;
  period: number;
  notIncludedPeriod?: boolean;
}

type PlanList = ConstructionPlan[];

const useConstructionPlans = (
  initialPlans: ConstructionPlan[],
  holidayUnixList: number[],

  onChange: () => void
) => {
  // 如果存在这个key,表示是保存过的草稿，否则就是原始模板
  const isDraft = !!initialPlans?.[0]["constructionPlanId"];

  // 计算iD的Key
  const idKey = isDraft ? "constructionPlanId" : "constructionPlanTemplateId";

  const [plans, setPlans] = useState<PlanList>([]);

  const globalStartDateRef = useRef<string>();

  // 使用 useRef 持久化存储
  const planMapRef = useRef<Map<number, ConstructionPlan>>(new Map());
  const dependencyGraphRef = useRef<Map<number, number[]>>(new Map());
  const planArrayRef = useRef<ConstructionPlan[]>([]); // 保持原始顺序

  // 是否跳过假期
  const isSkipHolidayRef = useRef<boolean>();

  // 计算结束日期
  const calculateFinishDate = (startDate: string, period: number): string => {
    return getPeriodEndDate(
      startDate,
      period,
      holidayUnixList,
      isSkipHolidayRef.current
    ).format("YYYY-MM-DD");
  };

  // 查找有效的开始时间（处理notIncludedPeriod情况）
  const findValidStartDate = (
    planId: number,
    visited = new Set<number>()
  ): string => {
    const planMap = planMapRef.current;
    const plan = planMap.get(planId);
    const planList = plans.length > 0 ? plans : initialPlans;

    const globalStartDate = globalStartDateRef.current;

    if (!plan || visited.has(planId)) return globalStartDate!;
    visited.add(planId);

    // 特殊项处理
    if (plan.constructionProjectName === "水电施工") return globalStartDate!;

    // 处理依赖项
    if (plan.prePlanId !== 0) {
      const dependency = planMap.get(plan.prePlanId);

      // 当依赖项不存在时，向前查找
      if (!dependency) {
        const planIndex = planList.findIndex((p) => p[idKey] === planId);

        let currentIndex = planIndex - 1;

        while (currentIndex >= 0) {
          const candidate = planList[currentIndex];

          // 检查notIncludedPeriod
          if (!candidate.notIncludedPeriod) {
            return calculateFinishDate(candidate.planFinishDate, 2);
          }

          // 如果当前项有notIncludedPeriod，继续向前找
          currentIndex--;
        }

        return globalStartDate!;
      }

      // 原有逻辑：处理notIncludedPeriod
      if (dependency.notIncludedPeriod) {
        return findValidStartDate(dependency[idKey], visited);
      }
      return calculateFinishDate(dependency.planFinishDate, 2);
    }

    // prePlanId=0时的处理
    const planIndex = planList.findIndex((p) => p[idKey] === planId);
    if (planIndex > 0) {
      const prevPlan = planList[planIndex - 1];
      if (prevPlan.notIncludedPeriod) {
        return findValidStartDate(prevPlan[idKey], visited);
      }
      return calculateFinishDate(prevPlan.planFinishDate, 2);
    }

    return globalStartDate!;
  };

  // 更新单个计划及其依赖项
  const updatePlanAndDependents = (planId: number, startDate?) => {
    const planMap = planMapRef.current;
    const dependencyGraph = dependencyGraphRef.current;
    const updatedPlans = new Map<number, ConstructionPlan>();
    const queue: number[] = [planId];
    const processed = new Set<number>();

    while (queue.length > 0) {
      const currentId = queue.shift()!;
      if (processed.has(currentId)) continue;

      const currentPlan = planMap.get(currentId);

      if (!currentPlan) continue;

      // 计算新的开始日期
      currentPlan.planStartDate =
        startDate && currentId == planId
          ? startDate
          : findValidStartDate(currentId);
      currentPlan.planFinishDate = calculateFinishDate(
        currentPlan.planStartDate,
        currentPlan.period
      );

      updatedPlans.set(currentId, { ...currentPlan });
      processed.add(currentId);

      // 将依赖当前计划的所有计划加入队列
      const dependents = dependencyGraph.get(currentId) || [];
      queue.push(...dependents);
    }

    return Array.from(updatedPlans.values());
  };

  // 更新所有计划
  const updateAllPlans = () => {
    const planMap = planMapRef.current;
    const planArray = planArrayRef.current;
    const updatedPlans: ConstructionPlan[] = [];

    // 按原始顺序处理
    planArray.forEach((plan) => {
      plan.planStartDate = findValidStartDate(plan[idKey]);

      plan.planFinishDate = calculateFinishDate(
        plan.planStartDate,
        plan.period
      );
      updatedPlans.push(plan);
      planMap.set(plan[idKey], plan);
    });

    return updatedPlans;
  };

  const updateAllFlag = useRef(false);
  useUpdateEffect(() => {
    if (updateAllFlag.current) {
      updateAllFlag.current = false;
      updateAllPlans();
    }
  }, [[plans]]);

  // 更新单个计划的开始日期
  const updatePlanByIndex = (newData: ConstructionPlan) => {
    // 因为可能是更新 是否计入工期状态
    // plans[index] = newData;

    const planId = newData[idKey];
    const planMap = planMapRef.current;
    planMap.set(planId, newData);

    let updatedPlans = updatePlanAndDependents(planId, newData.planStartDate);

    setPlans((prev) => {
      const newList = prev.map(
        (p) => updatedPlans.find((up) => up[idKey] === p[idKey]) || p
      );

      onChange()
      return newList;
    });
  };

  // 删除计划（唯一使用索引的地方）
  const deletePlan = (deleteIndex: number) => {
    setPlans((prev) => {
      const currentPlan = plans[deleteIndex];
      const planId = currentPlan[idKey];

      const planMap = new Map(prev.map((p) => [p[idKey], p]));

      const dependencyGraph = dependencyGraphRef.current;
      const planToDelete = planMap.get(planId);

      if (!planToDelete) return prev;

      // 1. 找出所有直接依赖项
      const dependents = dependencyGraph.get(planId) || [];

      // 2. 构建新数组（同时处理更新）
      const newPlans = prev.filter((p) => {
        if (p[idKey] === planId) return false;

        // 3. 更新依赖关系
        if (dependents.includes(p[idKey])) {
          p.prePlanId = planToDelete.prePlanId;

          // 4. 重新计算时间
          p.planStartDate = findValidStartDate(p[idKey]);
          p.planFinishDate = calculateFinishDate(p.planStartDate, p.period);
        }
        return true;
      });

      // 5. 更新引用
      dependencyGraphRef.current = new Map(dependencyGraph);
      dependencyGraphRef.current.delete(planId);
      dependents.forEach((depId) => {
        if (planToDelete.prePlanId !== 0) {
          dependencyGraphRef.current.get(planToDelete.prePlanId)?.push(depId);
        }
      });

      updateAllFlag.current = true;

      onChange()
      return newPlans;
    });
  };

  // 初始化数据结构（入口）
  const initializePlans = (initialStartDate, isSkipHoliday) => {
    const planMap = new Map<number, ConstructionPlan>();
    const dependencyGraph = new Map<number, number[]>();
    const planArray = [...initialPlans];

    initialPlans.forEach((plan) => {
      planMap.set(plan[idKey], plan);
      if (!dependencyGraph.has(plan.prePlanId)) {
        dependencyGraph.set(plan.prePlanId, []);
      }
      dependencyGraph.get(plan.prePlanId)?.push(plan[idKey]);
    });

    planMapRef.current = planMap;
    planArrayRef.current = planArray;
    isSkipHolidayRef.current = isSkipHoliday;
    dependencyGraphRef.current = dependencyGraph;
    globalStartDateRef.current = initialStartDate;

    onChange()
    setPlans(updateAllPlans());
  };

  return {
    plans,

    initializePlans,
    updatePlanByIndex,
    deletePlan,
  };
};

export default useConstructionPlans;
